package com.twb.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.twb.auth.common.LoginUserUtil;
import com.twb.auth.entity.twbResource.TwbResource;
import com.twb.auth.entity.twbResource.TwbResourceApi;
import com.twb.auth.entity.twbResource.dto.*;
import com.twb.auth.entity.twbResource.vo.*;
import com.twb.auth.mapper.TwbResourceMapper;
import com.twb.auth.service.ITwbResourceService;
import com.twb.core.base.entity.TwbPageInfo;
import com.twb.core.base.service.impl.BaseService;
import com.twb.core.constants.TwbConstants;
import com.twb.core.exception.ServiceException;
import com.twb.core.util.BeanUtils;
import com.twb.core.util.TwbPageUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName TwbResourceService
 * @Description 资源管理service
 * @author DSY
 * @date 2018年11月3日 下午10:13:20
 */
@Service("twbResourceService")
public class TwbResourceService extends BaseService<TwbResourceMapper,TwbResource> implements ITwbResourceService {

	@Autowired
	TwbResourceMapper twbResourceMapper;

	@Override
	public List<TwbResource> listResourceAll(String appId) {
		return twbResourceMapper.listResourceAll(appId);
	}

	@Override
	public List<TwbResource> listResourceByUserId(String userId, String appId) {
		List<TwbResource> rtn = twbResourceMapper.listResourceByUserId(userId, appId);
		List<TwbResource> listResourceAll = twbResourceMapper.listResourceAll(appId);
		rtn = getParentRes(rtn, listResourceAll);
		return rtn;
	}

	@Override
	public TwbPageInfo<SearchTwbResourceDto> searchTwbResource(SearchTwbResourceVo vo) {
		TwbPageUtil.startPage(vo);
		List<SearchTwbResourceDto> list = twbResourceMapper.searchTwbResource(vo);
		return TwbPageUtil.of(list);
	}

	@Override
	public List<SearchTwbResourceDto> searchTwbResourceList(SearchTwbResourceVo vo) {
		SearchTwbResourceVo allVo= new SearchTwbResourceVo();
		allVo.setProjectId(vo.getProjectId());
		allVo.setParentResId("all");
		List<SearchTwbResourceDto> all = twbResourceMapper.searchTwbResource(allVo);

		TwbPageUtil.orderBy(vo.getSorts());
		List<SearchTwbResourceDto> list = twbResourceMapper.searchTwbResource(vo);

		List<SearchTwbResourceDto> parentList = new ArrayList<SearchTwbResourceDto>();
		list.forEach(item -> {
			parentList.addAll(getParentList(all, item.getParentResId()));
		});

		list.addAll(parentList);

		// 去重
		list = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SearchTwbResourceDto::getId))), ArrayList::new));
		// 排序
		new SearchTwbResourceDto().sort(list);

		return list;
	}

	/**
	 * @Title getParentList
	 * @Description 根据子节点获取所有父节点
	 * @param all
	 * @param pid
	 * @return
	 * @author DHL
	 * @date 2022年3月19日 下午3:44:04
	 */
	private List<SearchTwbResourceDto> getParentList(List<SearchTwbResourceDto> all, String pid) {
		List<SearchTwbResourceDto> rtn = new ArrayList<SearchTwbResourceDto>();

		all.forEach(item -> {
			if(pid != null && pid.equalsIgnoreCase(item.getId())) {
				rtn.add(item);

				List<SearchTwbResourceDto> parentList = getParentList(all, item.getParentResId());

				rtn.addAll(parentList);
			}
		});

		return rtn;
	}


	@Override
	public List<SearchTwbResourceTreeDto> searchTwbResourceTree(SearchTwbResourceTreeVo vo) {
		return twbResourceMapper.searchTwbResourceTree(vo);
	}

	@Override
	public GetTwbResourceByIdDto getTwbResourceById(String id) {
		// TODO Auto-generated method stub
		return twbResourceMapper.getTwbResourceById(id);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean saveTwbResource(TwbResource resource) {
		Integer resSeq = twbResourceMapper.getMaxSeqByParentResId(resource.getParentResId());
		if (null == resSeq) {
			resSeq = 1;
		} else {
			resSeq = resSeq + 1;
		}
		resource.setResSeq(resSeq);
		resource.setStatus("1");//默认有效
		return this.save(resource);
	}

	@Override
	public List<SearchAuthResourceTreeDto> searchAuthResourceTree(SearchAuthResourceTreeVo vo) {

		vo.setLoginUserId(getLoginUser().getId());

		if (LoginUserUtil.isDeveloper()) {
			vo.setIsDeveloper("true");
		} else {
			vo.setIsDeveloper("false");
		}

		List<SearchAuthResourceTreeDto> list = null;
		if (vo.getType().equals(0)) {// 查询机构经办权限
			list = twbResourceMapper.listOrgResourceTreeByOrgId(vo.getBizId());
		} else {// 查询角色经办权限

			list = twbResourceMapper.listRoleResourceTreeByRoleId(vo);
		}
		return list;
	}

	@Override
	public List<SearchRoleAccreditResourceTreeDto> searchRoleAccreditResourceTree(SearchRoleAccreditResourceTreeVo vo) {

		vo.setLoginUserId(getLoginUser().getId());

		if (LoginUserUtil.isDeveloper()) {
			vo.setIsDeveloper("true");
		} else {
			vo.setIsDeveloper("false");
		}

		return twbResourceMapper.listRoleAccreditResourceTreeByRoleId(vo);
	}

	@Override
	public int deleteTwbResourceById(String id) {
		List<String> ids = listChildrenResIds(id);
		ids.add(id);

		// 删除角色经办资源
		twbResourceMapper.deleteRoleResourceByResId(ids);
		// 删除角色授权资源
		twbResourceMapper.deleteRoleAccreditResourceByResId(ids);
		// 删除机构资源
		twbResourceMapper.deleteOrgResourceByResId(ids);
		// 删除资源API配置
		twbResourceMapper.deleteApiResourceByResId(ids);

		// 删除资源
		return twbResourceMapper.deleteTwbResourceById(ids);
	}

	@Override
	public List<String> listChildrenResIds(String parentId) {
		TwbResource record = new TwbResource();
		record.setIsdel(0);
		List<String> ids = new ArrayList<String>();
		List<TwbResource> allList = this.list(record);
		getChildrenResIds(ids, allList, parentId);
		return ids;
	}

	/**
	 * @Title  getChildrenOrgIds
	 * @Description 递归获取部门下的子部门Id
	 * @param ids
	 * @param allList
	 * @param parentId
	 * @author DSY
	 * @date 2018年11月15日 下午5:03:49
	 */
	private void getChildrenResIds(List<String> ids, List<TwbResource> allList, String parentId) {
		List<TwbResource> tempList = new ArrayList<TwbResource>(allList);
		for (TwbResource res : allList) {
			if (StringUtils.isNotBlank(parentId) && parentId.equals(res.getParentResId())) {
				ids.add(res.getId());
				tempList.remove(res);
				getChildrenResIds(ids, tempList, res.getId());
			}
		}
	}

	/**
	 * @Title getParentRes
	 * @Description 根据子级获取所有父级
	 * @param list 子级集合
	 * @author DSY
	 * @date 2020年10月16日 上午10:03:02
	 */
	private List<TwbResource> getParentRes(List<TwbResource> list, List<TwbResource> listResourceAll) {
		List<TwbResource> userResources = new ArrayList<TwbResource>();

		if (CollectionUtils.isNotEmpty(list)) {

			if (CollectionUtils.isNotEmpty(listResourceAll)) {

				Map<String, TwbResource> resMap = new HashMap<String, TwbResource>();

				listResourceAll.forEach(item -> {
					resMap.put(item.getId(), item);
				});

				userResources.addAll(list);

				list.forEach(item -> {
					this.recursionParentRes(resMap, userResources, item);
				});

			}
		}

		return userResources;
	}

	/**
	 * @Title recursionParentRes
	 * @Description 递归获取父级
	 * @param resMap
	 * @param list
	 * @param res
	 * @author DSY
	 * @date 2020年10月16日 上午10:08:40
	 */
	private void recursionParentRes(Map<String, TwbResource> resMap, List<TwbResource> list, TwbResource res) {
		if (res != null) {
			TwbResource twbResource = resMap.get(res.getParentResId());

			if (twbResource != null) {
				if (!list.contains(twbResource)) {
					list.add(twbResource);
				}

				if (StringUtils.isNotBlank(twbResource.getParentResId())) {
					this.recursionParentRes(resMap, list, twbResource);
				}
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int saveResourceApi(String resourceId, String apiIds) {
		int deleteResult = twbResourceMapper.deleteResourceApiByResourceId(resourceId);
		if(StringUtils.isBlank(apiIds)) {
			return deleteResult;
		}
		String[] ids = apiIds.split(",");
		List<TwbResourceApi> list = new ArrayList<TwbResourceApi>();
		for (String apiId : ids) {
			TwbResourceApi resourceApi = new TwbResourceApi();
			resourceApi.setApiId(apiId);
			resourceApi.setResourceId(resourceId);
			list.add(resourceApi);
		}
		int result = 0;
		String dbType = twbConfigProperties.getDbType();
		if(dbType.equals(TwbConstants.DbType.ORACLE)) {
			result = twbResourceMapper.insertResourceApiBatchForOracle(list);
		} else {
			result = twbResourceMapper.insertResourceApiBatchForMysql(list);
		}
		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean updateTwbResourceById(UpdateTwbResourceByIdVo vo) {
		TwbResource record = null;
		boolean result = false;
		
		if (StringUtils.isEmpty(vo.getOldId()) || vo.getId().equalsIgnoreCase(vo.getOldId())){
			record = this.getById(vo.getId());
			if (null == record) {
				throw new ServiceException("2001", "资源不存在");
			}
			
			BeanUtils.copyProperties(vo, record);
			this.setUpdateInfo(record);
			result = this.updateById(record);
		} else {
			TwbResource countRecord = new TwbResource();
			countRecord.setId(vo.getId());
			long count = this.count(countRecord);
			if (count > 0) {
				throw new ServiceException("2001", "资源编号【" + vo.getId() + "】已存在");
			}

			record = this.getById(vo.getOldId());
			if (null == record) {
				throw new ServiceException("2001", "原资源不存在");
			}

			record.setId(vo.getId());
			
			BeanUtils.copyProperties(vo, record);
			this.setUpdateInfo(record);
			UpdateWrapper<TwbResource> updateWrapper = new UpdateWrapper<>();
			updateWrapper.eq("id", vo.getOldId());
			this.update(record, updateWrapper);

			int updateNum = twbResourceMapper.updateIdByOldId(vo.getId(), vo.getOldId());

			//  资源编辑，更新相关业务表
			if(updateNum > 0){
				UpdateWrapper<TwbResource> updateWrapperParentId = new UpdateWrapper<>();
				updateWrapperParentId.eq("parent_res_id", vo.getOldId());
				TwbResource updateParent = new TwbResource();
				updateParent.setParentResId(record.getId());
				this.update(updateParent, updateWrapperParentId);

				twbResourceMapper.updateOrgResId(vo.getId(), vo.getOldId());
				twbResourceMapper.updateRoleResId(vo.getId(), vo.getOldId());
				twbResourceMapper.updateRoleAccreditResId(vo.getId(), vo.getOldId());
				twbResourceMapper.updateApiResId(vo.getId(), vo.getOldId());
			}
			result = true;
		}

		return result;
	}

	@Override
	public int updateResourceStatusById(String id,String status) {
		List<String> ids = this.listChildrenResIds(id);
		ids.add(id);
		int result = twbResourceMapper.updateResourceStatusById(ids,status);
		return result;
	}
}
